package _thread_lock._lifecycle;

/**
 * @Author: huangya
 * @Date: 2020/12/31
 * @Description:
 */
public class ObservableThread<T> extends Thread implements Observable {

    private final TaskLifecycle<T> lifecycle;

    private final Task<T> task;

    private Cycle cycle;

    public ObservableThread(Task<T> task) {
        this(new EmptyTaskLifecycle(), task);
    }

    public ObservableThread(TaskLifecycle<T> lifecycle, Task<T> task) {
        super();
        this.lifecycle = lifecycle;
        this.task = task;
    }

    @Override
    public Cycle getCycle() {
        return this.cycle;
    }

    @Override
    public final void run() {
        update(Cycle.STARTED, null, null);
        try {
            update(Cycle.RUNNING, null, null);
            T result = task.call();
            update(Cycle.DONE, result, null);
        } catch (Exception e) {
            update(Cycle.ERROR, null, e);
        }
    }

    private void update(Cycle cycle, T result, Exception e){
        this.cycle = cycle;
        if(lifecycle==null){
            return;
        }
        try {
            switch (cycle) {
                case STARTED : lifecycle.onStart(currentThread());
                    break;
                case RUNNING : lifecycle.onRunning(currentThread());
                    break;
                case DONE : lifecycle.onFinish(currentThread(), result);
                    break;
                case ERROR : lifecycle.onError(currentThread(), e);
                    break;
            }
        } catch (Exception ex) {
            if(cycle == Cycle.ERROR){
                throw ex;
            }
            //todo..
        }
    }
}
